#ifndef __DEVICE_H__
#define __DEVICE_H__

#ifdef __cplusplus
extern "C" {
#endif

#include <stdint.h>

/*
 * @note 依赖项：
    "cbb_bit.h",    位操作 -- 必须
    "cbb_delay.h",  延时 -- 必须
    "cbb_mem.h"     内存管理 -- 可选
*/

// 延时函数接口
#include "cbb_delay.h"
#define DEV_DELAY_MS CBB_DELAY_MS

// 替换为自己的内存管理头文件 -- 不使用内存管理时可注释掉
#include "cbb_mem.h"
#define DEV_MALLOC(size) S_MALLOC(size)

// 不适用内存管理 -- 全局创建设备类和设备特征上下文结构体
#ifndef DEV_MALLOC
#define DEV_MALLOC(size) NULL
#endif

// 最大支持事件位数
#define MAX_EVENT_BITS 24

// 设备标志位
enum {
    FLAG_START = MAX_EVENT_BITS,

    FLAG_LOCK,  // 设备锁 -- 用于控制设备的访问权限
    FLAG_BUSY,  // 设备忙 -- 用于控制设备的忙闲状态,防止同时访问，针对os可使用互斥锁
};

// 获取设备接口
#define GET_DEVICE(pstDevice, type) ((type*)pstDevice->pvFeature)

// 设备注册声明
#define DEV_REG_DEC(name, type) \
Device_t* name##_register(type* pstSelf);  \

// 设备注册定义
#define DEV_REG_DEF(name, type) \
Device_t* name##_register(type* pstSelf){ \
    /* 输入参数检查 */  \
    if(NULL == pstSelf) return NULL; \
    /* 申请上下文结构体 */ \
    type* _pstSelf = DEV_MALLOC(sizeof(type)); \
    /* 上下文结构体检查 */ \
    if(NULL == _pstSelf) return NULL; \
    /* 复制结构体到上下文结构体 */ \
    memcpy(_pstSelf, pstSelf, sizeof(type)); \
    /* 注册设备 */ \
    Device_t* pstDevice = device_register(_pstSelf); \
    /* 返回设备 */  \
    return pstDevice; \
} \

// 设置设备忙
#define SET_DEVICE_BUSY(pstDevice, u8Busy) \
(u8Busy)?(pstDevice->u32Event |= (0x01 << FLAG_BUSY)) : (pstDevice->u32Event &= ~(0x01 << FLAG_BUSY))

// 获取设备忙
#define GET_DEVICE_BUSY(pstDevice) if((pstDevice->u32Event >> FLAG_BUSY) & 0x01) return DEV_BUSY

// 设置设备锁
#define SET_DEVICE_LOCK(pstDevice, u8Lock) \
(u8Lock)?(pstDevice->u32Event |= (0x01 << FLAG_LOCK)) : (pstDevice->u32Event &= ~(0x01 << FLAG_LOCK))

// 获取设备锁
#define GET_DEVICE_LOCK(pstDevice) if((pstDevice->u32Event >> FLAG_LOCK) & 0x01) return DEV_LOCK

// 设备检查
#define CHECK_DEVICE(pstDevice) \
        GET_DEVICE_LOCK(pstDevice); \
        GET_DEVICE_BUSY(pstDevice); \
        SET_DEVICE_BUSY(pstDevice, 1) \

// 设备返回
#define DEV_RETURN(val) \
        SET_DEVICE_BUSY(pstDevice, 0);\
        return (val);

// 定义IO状态
enum {
    IO_LOW = 0,    // 低电平
    IO_HIGH = 1    // 高电平
};

// 设备返回值
typedef enum DEV_RET{
    DEV_OK = 0,     // 成功
    DEV_ERR,        // 失败
    DEV_PARAM_ERR,  // 参数错误
    DEV_BUSY,       // 繁忙
    DEV_LOCK,       // 锁定
    DEV_TIMEOUT,    // 超时
}DEV_RET_t;

// 设备结构体
typedef struct Device{
    void* pvFeature;    // 设备上下文 
    uint32_t u32Event;  // 事件位
}Device_t;

/* 声明一个设备的 Feature 类型 */
#define DEVICE_FEATURE_DECLARE(name, hw_type, sw_type)  \
    typedef struct name {   \
        hw_type HW;         \
        sw_type SW;         \
    } name##_t

// 设备上下文举例

/*
DEVICE_FEATURE_DECLARE (
    name,
    struct {
        // 硬件相关的接口以及变量
    },
    struct {
        // 软件相关的接口以及变量
    }
)

Expaned:

typedef struct Device_Context{
    struct HW {
        // 硬件相关的接口以及变量
    };
    struct SW {
        // 软件相关的接口以及变量
    };
}Device_Context_t;
*/

/**
 * @brief 注册设备
 * @param pvFeature 设备特有功能
 * @return Device_t* 注册成功返回设备结构体指针，失败返回NULL
 * 
 * @note pvFeature必须是全局存在的变量
 */
Device_t*
device_register(void* pvFeature); 

/**
 * @brief 获取设备事件
 * @param pstDevice 设备结构体指针
 * @param bit 事件位
 * @return uint8_t 事件位状态 
 *
 * @note 返回1表示事件发生，0表示事件未发生
 */
uint8_t 
get_device_event(Device_t* pstDevice, uint8_t bit);

/**
 * @brief 清除设备事件
 * @param pstDevice 设备结构体指针
 * @param bit 事件位
 * @return @see DEV_RET_t
 */
DEV_RET_t 
clear_device_event(Device_t* pstDevice, uint8_t bit);

/**
 * @brief 设置设备事件
 * @param pstDevice 设备结构体指针
 * @param bit 事件位
 * @return @see DEV_RET_t
 */
DEV_RET_t 
set_device_event(Device_t* pstDevice, uint8_t bit);

#ifdef __cplusplus
}
#endif

#endif /* __DEVICE_H__ */
